package util

class AssertableBuilder extends BuilderSupport {

    def expectations = []
    def record = true

    def replay() {
        record = false
    }

    def verify() {
        if(expectations.size() != 0) {
            println("The following expectations did not happen:")
            println("---")
            expectations.each {
                println(it)
            }
            throw new AssertionException("See errors")
        }
    }

    protected void setParent(Object o, Object o1) {
    }

    protected Object createNode(Object node) {
        handle {
            new TestNode(node.toString())
        }
    }

    protected Object createNode(Object node, Object o1) {
        handle {
            new TestNode(node.toString(), o1)
        }
    }

    protected Object createNode(Object node, Map map) {
        handle {
            new TestNode(node.toString(), map)
        }
    }

    protected Object createNode(Object node, Map map, Object o1) {
        handle {
            new TestNode(node.toString(), map, o1)
        }
    }

    def handle(callback) {
        if(record) {
            expectations << callback()
        } else {
            if(callback() == expectations[0]) {
                expectations.remove(0)
            }
        }
    }
    
}

class TestNode {

    String nodeName
    Map attributes
    Object value

    TestNode(String nodeName) {
        this.nodeName = nodeName
    }

    TestNode(String nodeName, Object value) {
        this.nodeName = nodeName
        this.value = value
    }

    TestNode(String nodeName, Map attributes) {
        this.nodeName = nodeName
        this.attributes = attributes
    }

    TestNode(String nodeName, Map attributes, Object value) {
        this.nodeName = nodeName
        this.attributes = attributes
        this.value = value
    }

    public String toString() {
        return "${nodeName} attributes: ${attributes} value: ${value}"
    }

    public boolean equals(Object obj) {
        return nodeName == obj.nodeName && attributes == obj.attributes && value == obj.value
    }

}